use cgmath::{ortho, Matrix4, Vector2, Vector3, Zero};

#[rustfmt::skip]
pub const OPENGL_TO_WGPU_MATRIX: cgmath::Matrix4<f32> = cgmath::Matrix4::new(
    1.0, 0.0, 0.0, 0.0,
    0.0, 1.0, 0.0, 0.0,
    0.0, 0.0, 0.5, 0.5,
    0.0, 0.0, 0.0, 1.0,
);

pub struct Camera {
    position: Vector3<f32>,
    proj: Matrix4<f32>,
}

impl Camera {
    pub fn new(proj: Matrix4<f32>) -> Self {
        Self {
            position: Vector3::zero(),
            proj,
        }
    }

    pub fn from_ortho(width: f32, height: f32) -> Self {
        println!("View port width {width} height {height}");
        Self {
            position: Vector3::zero(),
            proj: ortho(0.0, width, 0.0, height, -1.0, 1.0),
        }
    }

    pub fn set_projection<P: Into<Matrix4<f32>>>(&mut self, proj: P) {
        self.proj = proj.into();
    }

    pub fn set_ortho(&mut self, width: f32, height: f32) {
        self.proj = ortho(0.0, width, 0.0, height, -1.0, 1.0);
    }

    pub fn set_position2d(&mut self, position: Vector2<f32>) {
        self.position.x = position.x;
        self.position.y = position.y;
    }

    pub fn set_position(&mut self, position: Vector3<f32>) {
        self.position = position;
    }

    pub fn combination(&self) -> Matrix4<f32> {
        OPENGL_TO_WGPU_MATRIX * self.proj * Matrix4::from_translation(-self.position)
    }
}
